#include <unistd.h>

#include "../comm/util.hpp"
#include "compile.hpp"
#include "runner.hpp"

#include <sys/time.h>
#include <sys/resource.h>

using namespace ns_util;
using namespace ns_compiler;
using namespace ns_runner;

void testCompile()
{
    // 子进程
    std::string file_name = "test2";
    execlp("g++", "g++", "-o", "a.out",
           "test2.cc", "-std=c++11", nullptr);

    // execlp("ls", "ls", "-al", nullptr);
}

struct test
{
    void p()
    {
        printf("ahha\n");
    }
};

void testClass()
{
    struct test *pt = new test;
    pt->p();
}

void testrlimit()
{
    // struct rlimit s;
    // s.rlim_cur = 1;
    // s.rlim_max = RLIM_INFINITY;

    // setrlimit(RLIMIT_CPU, &s);

    // while(1);

    int count = 0;
    while (true)
    {
        int *p = new int[1024 * 1024];
        count++;

        LOG(INFO, "已申请 %d MB\n", count * 4);
        sleep(1);
    }
}

void testfile()
{
    // std::string content;
    // FileUtil::ReadFile("./temp/code.cpp", &content, true);
    // std::cout << content << std::endl;
    // std::cout << "-----------" << std::endl;

    // testfile();
    // printf("执行execl\n");
    // std::string path = "./temp/1729579657879_1.exe";// ./temp/1729579657879_1.exe
    // execl(path.c_str(), path.c_str(), nullptr);

    pid_t id = fork();

    if (id == 0)
    {
        std::string path = "./temp/1729580735698_1.exe"; // ./temp/1729579657879_1.exe
        execl(path.c_str(), path.c_str(), nullptr);

        exit(1);
    }
    else
    {
        int status;
        waitpid(id, &status, 0);
        LOG(INFO, "sig: %d\n", status & 0x7f);
    }
}
static void SourceLimit(int cpu_limit, int mem_limit)
{
    struct rlimit cpu;
    cpu.rlim_cur = cpu_limit;
    cpu.rlim_max = RLIM_INFINITY;

    struct rlimit mem;
    mem.rlim_cur = mem_limit;
    mem.rlim_max = RLIM_INFINITY;

    setrlimit(RLIMIT_CPU, &cpu);// 24号信号
    setrlimit(RLIMIT_AS, &mem);// 
}
void handle_sig(int signum)
{
    printf("i am %d\n", signum);
}
void testlimit()
{
    SourceLimit(1, 1024);
    char* pc = new char[1024*1024];
}

static int Run(const std::string& file_name, int cpu_limit, int mem_limit)
{
    std::string _execute = PathUtil::Exe(file_name);
    std::string _stdin = PathUtil::Stdin(file_name);
    std::string _stdout = PathUtil::Stdout(file_name);
    std::string _stderr = PathUtil::Stderr(file_name);
    
    umask(0);
    int _in_fd = open(_stdin.c_str(), O_CREAT | O_RDONLY, 0644);
    int _out_fd = open(_stdout.c_str(), O_CREAT | O_WRONLY, 0644);
    int _err_fd = open(_stderr.c_str(), O_CREAT | O_WRONLY, 0644);
    if(_in_fd < 0 || _out_fd < 0 || _err_fd < 0)
    {
        LOG(FATAL, "运行时打开文件失败\n");
        return -1;
    }

    pid_t id = fork();
    if(id < 0)
    {
        close(_in_fd);
        close(_out_fd);
        close(_err_fd);

        LOG(FATAL, "运行时创建子进程失败\n");
        return -2;
    }
    else if(id == 0)
    {
        LOG(INFO, "子进程\n");
        dup2(_in_fd, 0);
        dup2(_out_fd, 1);
        dup2(_err_fd, 2);
        LOG(INFO, "资源限制\n");
        SourceLimit(cpu_limit, mem_limit);
        LOG(INFO, "程序替换 execl 执行: %s\n", _execute.c_str());
        execl(_execute.c_str(), _execute.c_str(), nullptr);
        exit(1);
    }
    else  
    {
        close(_in_fd);
        close(_out_fd);
        close(_err_fd);
        int status = 0;
        waitpid(id, &status, 0);
        LOG(INFO, "运行结束，返回值：%d\n", status & 0x7f); 

        return status & 0x7f;
    }
}

int main()
{
    
    std::cout << Run("1731657231124_1", 6, 3000000) << std::endl;
    return 0;
}